home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Musik / Misc / Amster / Source / navigator.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-01  |  13.8 KB  |  456 lines

  1. /*
  2. ** Amster - Navigator
  3. ** by Jacob Laursen <laursen@myself.com>
  4. **
  5. ** (work in progress!)
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include <proto/dos.h>
  13. #include <proto/socket.h>
  14. #include <proto/utility.h>
  15.  
  16. #include <netdb.h>
  17. #include <sys/time.h>
  18. #include <sys/socket.h>
  19. #include <sys/ioctl.h>
  20. #include <netinet/tcp.h>
  21. #include <bsdsocket/socketbasetags.h>
  22. #include <error.h>
  23. #include <time.h>
  24.  
  25. #include <MUI/NListview_mcc.h>
  26.  
  27. #include "include/config.h"
  28. #include "include/gui.h"
  29. #include "include/info.h"
  30. #include "include/mui.h"
  31. #include "include/navigator.h"
  32. #include "include/prefs.h"
  33. #include "include/share.h"
  34.  
  35. #include "include/protos.h"
  36. #include "amster_Cat.h"
  37.  
  38. /* Global variables */
  39.  
  40. BOOL ServerListChanged = FALSE;
  41.  
  42. /* Private prototypes */
  43.  
  44. void LoadServerList(struct NavigatorData *data);
  45. void SaveServerList(struct NavigatorData *data);
  46. void MarkServerOnline(struct NavigatorData *data, char *server);
  47. MUIF ServerListDisplay(REG(a2) char **array, REG(a1) struct ServerEntry *entry);
  48. MUIF ServerListCompare(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm);
  49. MUIF ServerListDestruct(REG(a2) APTR pool, REG(a1) struct ServerEntry *entry);
  50. MUIF ServerString(REG(a0) struct Hook *hook, REG(a1) APTR *contents);
  51.  
  52.  
  53. MUIF NavigatorDispatch(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
  54. {
  55.     struct NavigatorData *data;
  56.     struct ServerEntry *entry;
  57.     char *buf;
  58.  
  59.     switch (msg->MethodID) {
  60.         case OM_NEW:
  61.             return(NavigatorNew(cl, obj, (APTR)msg));
  62.         case NAVI_CONNECT:
  63.             data = INST_DATA(cl, obj);
  64.             if (gui_napon) nap_logout();
  65.             get(data->ST_Server, MUIA_String_Contents, &buf);
  66.             if (!gui_napon) {
  67.                 nap_login_fromlist(buf);
  68.             }
  69.             return(NULL);
  70.         case NAVI_GETSERVER:
  71.             data = INST_DATA(cl, obj);
  72.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  73.             if (entry) {
  74.                 set(data->ST_Server,  MUIA_String_Contents, entry->Name);
  75.                 set(data->ST_Comment, MUIA_String_Contents, entry->Comment);
  76.             }
  77.             return(NULL);
  78.         case NAVI_ADDSERVER:
  79.             {
  80.             BOOL selected = FALSE;
  81.  
  82.             data = INST_DATA(cl, obj);
  83.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  84.             if (entry) selected = TRUE;    /* One entry is already selected */
  85.  
  86.             if (entry = malloc(sizeof(struct ServerEntry))) {
  87.                 entry->LastOnline = 0;
  88.                 if (selected) {
  89.                     /* We clear the fields instead of dublicating selected entry */
  90.                     entry->Name = strdup(MSG_NAVIGATOR_NEW);
  91.                     entry->Comment = strdup("");
  92.                 }
  93.                 else {
  94.                     get(data->ST_Server, MUIA_String_Contents, &buf);
  95.                     entry->Name = strdup(buf);
  96.                     get(data->ST_Comment, MUIA_String_Contents, &buf);
  97.                     entry->Comment = strdup(buf);
  98.                 }
  99.                 DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  100.                 set(data->LV_Server, MUIA_NList_First, MUIV_NList_Active_Bottom);
  101. /*                DoMethod(data->LV_Server, MUIM_NList_Jump, MUIV_NList_Jump_Active);*/
  102.                 ServerListChanged = TRUE;
  103.             }
  104.             }
  105.             return(NULL);
  106.         case NAVI_REMOVESERVER:
  107.             data = INST_DATA(cl, obj);
  108.             DoMethod(data->LV_Server, MUIM_NList_Remove, MUIV_NList_Remove_Active);
  109.             ServerListChanged = TRUE;
  110.             return(NULL);
  111.         case NAVI_REDRAWSERVER:
  112.             {
  113.             struct ServerEntry *entry;
  114.             APTR *contents = (APTR)(((muimsg)msg)->arg1);
  115.             data = INST_DATA(cl, obj);
  116.  
  117.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  118.             if (entry) {
  119.                 if (*(contents+1) == 0) entry->Name = strdup(*contents);
  120.                 else entry->Comment = strdup(*contents);
  121.                 DoMethod(data->LV_Server, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  122.                 ServerListChanged = TRUE;
  123.             }
  124.             return(NULL);
  125.             }
  126.         case NAVI_LOAD:
  127.             data = INST_DATA(cl, obj);
  128.             LoadServerList(data);
  129.             return(NULL);
  130.         case NAVI_SAVE:
  131.             data = INST_DATA(cl, obj);
  132.             SaveServerList(data);
  133.             return(NULL);
  134.         case NAVI_MARKSERVER:
  135.             data = INST_DATA(cl, obj);
  136.             MarkServerOnline(data, (char *)(((muimsg)msg)->arg1));
  137.             return(NULL);
  138.     }
  139.     return(DoSuperMethodA(cl, obj, msg));
  140. }
  141.  
  142.  
  143. ULONG NavigatorNew(struct IClass *cl, Object *obj, struct opSet *msg)
  144. {
  145.     static const struct Hook ServerListDispHook = { {NULL, NULL}, &ServerListDisplay,  NULL, NULL };
  146.     static const struct Hook ServerListCompHook = { {NULL, NULL}, &ServerListCompare,  NULL, NULL };
  147.     static const struct Hook ServerListDestHook = { {NULL, NULL}, &ServerListDestruct, NULL, NULL };
  148.     static const struct Hook ServerStringHook   = { {NULL, NULL}, &ServerString,       NULL, NULL };
  149.  
  150.     struct NavigatorData *data;
  151.  
  152.     Object *LV_Server, *ST_Server, *ST_Comment;
  153.     Object *BT_ConnectConnect, *BT_ConnectAdd, *BT_ConnectRemove;
  154.  
  155.     if (obj = (Object *)DoSuperNew(cl, obj,
  156.         MUIA_HelpNode, "navi",
  157.         MUIA_Window_Title, MSG_NAVIGATOR_TITLE,
  158.         MUIA_Window_ID, MAKE_ID('N','A','V','I'),
  159.         WindowContents, VGroup,
  160.             Child, LV_Server = NListviewObject,
  161.                 MUIA_NList_Input, TRUE,
  162.                 MUIA_NListview_NList, NListObject,
  163.                     InputListFrame,
  164.                     MUIA_NList_ListBackground, MUII_ListBack,
  165.                     MUIA_NList_TitleBackground, MUII_ListBack,
  166.                     MUIA_NList_Title, TRUE,
  167.                     MUIA_NList_Format, "BAR,BAR,",
  168.                     MUIA_NList_DisplayHook, &ServerListDispHook,
  169.                     MUIA_NList_CompareHook2, &ServerListCompHook,
  170.                     MUIA_NList_DestructHook, &ServerListDestHook,
  171.                 End,
  172.             End,
  173.             Child, ColGroup(2),
  174.                 Child, Label2(MSG_NAVIGATOR_SERVER),
  175.                 Child, ST_Server = StringObject,
  176.                     MUIA_HorizWeight, 400,
  177.                     StringFrame,
  178.                 End,
  179.                 Child, Label2(MSG_NAVIGATOR_COMMENT),
  180.                 Child, ST_Comment = StringObject,
  181.                     MUIA_HorizWeight, 400,
  182.                     StringFrame,
  183.                 End,
  184.             End,
  185.             Child, RectangleObject,
  186.                 MUIA_FixHeight, 8,
  187.                 MUIA_Rectangle_HBar, TRUE,
  188.             End,
  189.             Child, HGroup,
  190.                 Child, BT_ConnectConnect = SimpleButton(MSG_NAVIGATOR_CONNECT_GAD),
  191.                 Child, BT_ConnectRemove  = SimpleButton(MSG_NAVIGATOR_REMOVE_GAD),
  192.                 Child, BT_ConnectAdd     = SimpleButton(MSG_NAVIGATOR_ADD_GAD),
  193.             End,
  194.         End,
  195.         TAG_MORE, msg->ops_AttrList))
  196.     {
  197.         data = INST_DATA(cl, obj);
  198.         data->LV_Server  = LV_Server;
  199.         data->ST_Server  = ST_Server;
  200.         data->ST_Comment = ST_Comment;
  201.  
  202.         DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, obj, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  203.  
  204.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick,  MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  205.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
  206.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType,    MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark,  MUIV_TriggerValue);
  207.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType2,   MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
  208.  
  209.         DoMethod(BT_ConnectConnect, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_CONNECT);
  210.         DoMethod(BT_ConnectRemove,  MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_REMOVESERVER);
  211.         DoMethod(BT_ConnectAdd,     MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_ADDSERVER);
  212.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, NAVI_CONNECT);
  213.  
  214.         LoadServerList(data);
  215.  
  216.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_Active, MUIV_EveryTime, obj, 1, NAVI_GETSERVER);
  217.  
  218.         set(ST_Server, MUIA_String_AttachedList, LV_Server);
  219.  
  220.         DoMethod(ST_Server,  MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 0);
  221.         DoMethod(ST_Comment, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 1);
  222.  
  223.         return((ULONG)obj);
  224.     }
  225.     return(0);
  226. }
  227.  
  228.  
  229. void LoadServerList(struct NavigatorData *data)
  230. {
  231.     BPTR fh;
  232.     char buf[1024];
  233.     int line = 0;
  234.     struct ServerEntry *entry;
  235.     LONG argarray[] = { NULL, NULL, NULL };
  236.     UBYTE *argstr = "HOST/A,LASTUSED/A/N,COMMENT/K";
  237.     struct RDArgs *rdargs;
  238.  
  239.     if (fh = Open("PROGDIR:Amster.servers", MODE_OLDFILE)) {
  240.         while (FGets(fh, buf, sizeof(buf))) {
  241.             line++;
  242.             if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  243.                 rdargs->RDA_Buffer = NULL;
  244.                 rdargs->RDA_Source.CS_Buffer = buf;
  245.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  246.                 argarray[2] = 0;
  247.                 if (ReadArgs(argstr, argarray, rdargs)) {
  248.                     if (entry = malloc(sizeof(struct ServerEntry))) {
  249.                         entry->Name = strdup((char *)argarray[0]);
  250.                         entry->LastOnline = *((long *)argarray[1]);
  251.                         if (argarray[2]) entry->Comment = strdup((char *)argarray[2]);
  252.                         else entry->Comment = strdup("");
  253.                         entry->Ping = -1;
  254.                         DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  255.                     }
  256.                 }
  257.                 else gui_debugf((char *)MSG_PARSE_ERROR, "PROGDIR:Amster.servers", line);
  258.                 FreeDosObject(DOS_RDARGS, rdargs);
  259.             }
  260.         }
  261.         Close(fh);
  262.         DoMethod(data->LV_Server, MUIM_NList_Sort);
  263.     }
  264. }
  265.  
  266.  
  267. void SaveServerList(struct NavigatorData *data)
  268. {
  269.     struct ServerEntry *entry;
  270.     BPTR fh;
  271.     char buf[1024], *tmp;
  272.     int i;
  273.  
  274.     fh = Open("PROGDIR:Amster.servers", MODE_NEWFILE);
  275.     if (!fh) return;
  276.  
  277.     for (i=0; ; i++) {
  278.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  279.         if (!entry) break;
  280.         if (entry->Comment) {
  281.             if (entry->Comment[0] != '\0') {
  282.                 tmp = strrep(entry->Comment, "\"", "*\"");
  283.                 sprintf(buf, "%s %ld COMMENT \"%s\"\n", entry->Name, entry->LastOnline, tmp);
  284.                 free(tmp);
  285.             }
  286.             else sprintf(buf, "%s %ld\n", entry->Name, entry->LastOnline);
  287.         }
  288.         else sprintf(buf, "%s %ld\n", entry->Name, entry->LastOnline);
  289.         Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
  290.     }
  291.  
  292.     Close(fh);
  293.     ServerListChanged = FALSE;
  294. }
  295.  
  296.  
  297. void MarkServerOnline(struct NavigatorData *data, char *server)
  298. {
  299.     struct ServerEntry *entry=0;
  300.     struct DateStamp *ds, *rds;
  301.     int i;
  302.     BOOL new = FALSE;
  303.  
  304.     for (i=0; ; i++) {
  305.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  306.         if (!entry) break;
  307.         if (strcmp(server, entry->Name) == 0) break;
  308.     }
  309.     if (!entry) {    /* Server not already on list */
  310.         if (prf->ServerList < 2) return;
  311.         if (entry = malloc(sizeof(struct ServerEntry))) {
  312.             entry->Name = strdup(server);
  313.             entry->LastOnline = 0;    /* In case we don't succeed later on... */
  314.             entry->Comment = strdup("");
  315.             entry->Ping = -1;
  316.             new = TRUE;
  317.         }
  318.     }
  319.  
  320.     if (ds = malloc(sizeof(struct DateStamp))) {
  321.         memset(ds, 0, sizeof(struct DateStamp));
  322.         if (rds = DateStamp(ds)) {
  323.             entry->LastOnline = rds->ds_Days*24*60*60 + rds->ds_Minute*60 + rds->ds_Tick/50;
  324.             if (new)
  325.                 DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  326.             else
  327.                 DoMethod(data->LV_Server, MUIM_NList_Redraw, i);
  328.             ServerListChanged = TRUE;
  329.         }
  330.         free(ds);
  331.     }
  332. }
  333.  
  334.  
  335. MUIF ServerListDisplay(REG(a2) char **array, REG(a1) struct ServerEntry *entry)
  336. {
  337.     struct DateTime dt;
  338.     static char buf[LEN_DATSTRING*2+6], buf2[20];
  339.     char datestring[LEN_DATSTRING], timestring[LEN_DATSTRING];
  340.  
  341.     if (entry) {
  342.         *array++ = entry->Name;
  343.         if (entry->LastOnline == 0) *array++ = "\33r-";
  344.         else {
  345.                 dt.dat_Stamp.ds_Days   = (entry->LastOnline)/(60*60*24);
  346.                 dt.dat_Stamp.ds_Minute = ((entry->LastOnline)%(60*60*24))/60;
  347.                 dt.dat_Stamp.ds_Tick   = ((entry->LastOnline)%60)*TICKS_PER_SECOND;
  348.                 dt.dat_Format = FORMAT_DOS;
  349.                 dt.dat_Flags = DTF_SUBST;
  350.                 dt.dat_StrDay = NULL;
  351.                 dt.dat_StrDate = datestring;
  352.                 dt.dat_StrTime = timestring;
  353.                 if (DateToStr(&dt)) {
  354.                     sprintf(buf, "\33r%s %s", datestring, timestring);
  355.                     *array++ = buf;
  356.                 }
  357.                 else *array++ = "\33r-";
  358.         }
  359.         *array++ = entry->Comment;
  360.  
  361.         if (entry->Ping >= 0) {
  362.             sprintf(buf2, "%ld", entry->Ping);
  363.             *array   = buf2;
  364.         }
  365.         else *array = "-";
  366.     }
  367.     else {
  368.         *array++ = (char *)MSG_NAVIGATOR_LIST_SERVER;
  369.         *array++ = (char *)MSG_NAVIGATOR_LIST_LASTONLINE;
  370.         *array++ = (char *)MSG_NAVIGATOR_LIST_COMMENT;
  371.         *array   = (char *)MSG_NAVIGATOR_LIST_PING;
  372.     }
  373.  
  374.     return 0;
  375. }
  376.  
  377.  
  378. MUIF ServerListCompare(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm)
  379. {
  380.     struct ServerEntry *entry1 = ncm->entry1;
  381.     struct ServerEntry *entry2 = ncm->entry2;
  382.     LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  383.     LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  384.     ULONG result = 0;
  385.  
  386.     if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
  387.  
  388.     if (col1 == 0) {
  389.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  390.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  391.         else
  392.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  393.     }
  394.     else if (col1 == 1) {
  395.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  396.             result = entry2->LastOnline - entry1->LastOnline;
  397.         else
  398.             result = entry1->LastOnline - entry2->LastOnline;
  399.     }
  400.     else if (col1 == 2) {
  401.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  402.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  403.         else
  404.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  405.     }
  406.     else if (col1 == 3) {
  407.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  408.             result = entry2->Ping - entry1->Ping;
  409.         else
  410.             result = entry1->Ping - entry2->Ping;
  411.     }
  412.  
  413.     if ((result != 0) || (col1 == col2)) return (result);
  414.  
  415.     if (col2 == 0) {
  416.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  417.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  418.         else
  419.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  420.     }
  421.     else if (col2 == 1) {
  422.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  423.             result = entry2->LastOnline - entry1->LastOnline;
  424.         else
  425.             result = entry1->LastOnline - entry2->LastOnline;
  426.     }
  427.     else if (col2 == 2) {
  428.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  429.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  430.         else
  431.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  432.     }
  433.     else if (col2 == 3) {
  434.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  435.             result = entry2->Ping - entry1->Ping;
  436.         else
  437.             result = entry1->Ping - entry2->Ping;
  438.     }
  439.  
  440.     return (result);
  441. }
  442.  
  443.  
  444. MUIF ServerListDestruct(REG(a2) APTR pool, REG(a1) struct ServerEntry *entry)
  445. {
  446.     free(entry);
  447.     return 0;
  448. }
  449.  
  450.  
  451. MUIF ServerString(REG(a0) struct Hook *hook, REG(a1) APTR *contents)
  452. {
  453.     DoMethod(gui->WI_Navigator, NAVI_REDRAWSERVER, contents);
  454.     return 0;
  455. }
  456.